﻿//-------------------------------------------------------------------
//	Copyright (c) 2010-2014  Zhirnov Andrey
//	This file is part of the "UX Standard Lib" project.
//	See copyright notice in "UX_STL_Ext.h".
//-------------------------------------------------------------------

#include "GLRenderBuffer.h"
#include "GLFrameBuffer.h"
#include "GLObjectManager.h"

namespace UX_STL
{
namespace GLShell
{
	
//-------------------------- GLRenderBuffer -----------------------//
/*
=================================================
	конструктор
=================================================
*/
	GLRenderBuffer::GLRenderBuffer(): _uID(0)
	{
	}
	
/*
=================================================
	деструктор
=================================================
*/
	GLRenderBuffer::~GLRenderBuffer()
	{
		if ( _uID != 0 )
		{
			GLOM()->DeleteRenderbuffers( 1, &_uID );
			_uID = 0;
		}
	}

/*
=================================================
	создание рендербуфера
=================================================
*/
	bool GLRenderBuffer::Create(gl_rt_format::type eFormat, const uvec3 &vDim, uint8 uSamples)
	{
		const uint	u_color_samples = uSamples >> 1;

		if ( !C_GL_NV_framebuffer_multisample_coverage or uSamples < 2 )
			return Create( vDim.xy(), eFormat, uSamples );
		else
			return Create( vDim.xy(), eFormat, uSamples, u_color_samples < 2 ? uSamples : u_color_samples );
	}

/*
=================================================
	создание рендербуфера
=================================================
*/
	bool GLRenderBuffer::Create(const uvec2 &vDim, gl_rt_format::type eFormat, uint uSamples)
	{
		CHECK_ERR( uSamples <= (uint)C_GL_MAX_COLOR_TEXTURE_SAMPLES );

		Destroy();
		CHECK_ERR( GLOM()->GenRenderbuffers( 1, &_uID ) );

		_vDimension	= uvec3( vDim, 0 );
		_eIFormat	= eFormat;

		if ( C_GL_EXT_framebuffer_multisample and uSamples > 1 ) {
			GL_CALL( glNamedRenderbufferStorageMultisample( _uID, uSamples, eFormat, vDim.x, vDim.y ) );
		} else {
			GL_CALL( glNamedRenderbufferStorage( _uID, eFormat, vDim.x, vDim.y ) );
		}
		return true;
	}
	
/*
=================================================
	создание рендербуфера с CSAA
=================================================
*/
	bool GLRenderBuffer::Create(const uvec2 &vDim, gl_rt_format::type eFormat, uint uCoverageSamples, uint uColorSamples)
	{
		CHECK_ERR( uCoverageSamples >= 2 and uColorSamples >= 2 );
		CHECK_ERR( uCoverageSamples <= (uint)C_GL_MAX_COLOR_TEXTURE_SAMPLES and
						uColorSamples <= (uint)C_GL_MAX_COLOR_TEXTURE_SAMPLES );
		CHECK_ERR( C_GL_NV_framebuffer_multisample_coverage );

		Destroy();
		CHECK_ERR( GLOM()->GenRenderbuffers( 1, &_uID ) );
		
		_vDimension	= uvec3( vDim, 0 );
		_eIFormat	= eFormat;

		GL_CALL( glNamedRenderbufferStorageMultisampleCoverageNV( _uID, uCoverageSamples, uColorSamples, eFormat, vDim.x, vDim.y ) );
		return true;
	}
	
/*
=================================================
	удаление рендербуфера
=================================================
*/
	void GLRenderBuffer::Destroy()
	{
		if ( _uID != 0 )
		{
			GLOM()->DeleteRenderbuffers( 1, &_uID );
			_uID = 0;
		}
		_eIFormat	= gl_rt_format::_UNKNOWN;
		_vDimension	= uvec3();
	}
	
/*
=================================================
	подключает рендербуфер к текстуре,
	являющейся рендертаргетом (?)
=================================================
*/
	bool GLRenderBuffer::AttachToTexture(GLTexture *pTex) const
	{
		CHECK_ERR( C_GL_NV_explicit_multisample );
		CHECK_ERR( pTex->Target() == GL_TEXTURE_RENDERBUFFER_NV );

		GL_CALL_R( glTextureRenderbuffer( pTex->Id(), pTex->Target(), _uID ) );
		return true;
	}
	
/*
=================================================
	
=================================================
*/
	bool GLRenderBuffer::GetInfo(GLRenderBufferInfo &sInfo) const
	{
		bool	ret	 = true;
		GLint	temp = 0;

		GL_CALL_BA( glGetNamedRenderbufferParameteriv( _uID, GL_RENDERBUFFER_WIDTH,			(GLint *)& sInfo.vDimension.x ), ret );
		GL_CALL_BA( glGetNamedRenderbufferParameteriv( _uID, GL_RENDERBUFFER_HEIGHT,		(GLint *)& sInfo.vDimension.y ), ret );
		GL_CALL_BA( glGetNamedRenderbufferParameteriv( _uID, GL_RENDERBUFFER_INTERNAL_FORMAT, & temp ), ret );
		sInfo.eIFormat = (gl_rt_format::type) temp;

		GL_CALL_BA( glGetNamedRenderbufferParameteriv( _uID, GL_RENDERBUFFER_SAMPLES,		(GLint *)& sInfo.uSamples), ret );
		GL_CALL_BA( glGetNamedRenderbufferParameteriv( _uID, GL_RENDERBUFFER_RED_SIZE,		(GLint *)& sInfo.aCompSize[GLRenderBufferInfo::R] ), ret );
		GL_CALL_BA( glGetNamedRenderbufferParameteriv( _uID, GL_RENDERBUFFER_GREEN_SIZE,	(GLint *)& sInfo.aCompSize[GLRenderBufferInfo::G] ), ret );
		GL_CALL_BA( glGetNamedRenderbufferParameteriv( _uID, GL_RENDERBUFFER_BLUE_SIZE,		(GLint *)& sInfo.aCompSize[GLRenderBufferInfo::B] ), ret );
		GL_CALL_BA( glGetNamedRenderbufferParameteriv( _uID, GL_RENDERBUFFER_ALPHA_SIZE,	(GLint *)& sInfo.aCompSize[GLRenderBufferInfo::A] ), ret );
		GL_CALL_BA( glGetNamedRenderbufferParameteriv( _uID, GL_RENDERBUFFER_DEPTH_SIZE,	(GLint *)& sInfo.aCompSize[GLRenderBufferInfo::DEPTH] ), ret );
		GL_CALL_BA( glGetNamedRenderbufferParameteriv( _uID, GL_RENDERBUFFER_STENCIL_SIZE,	(GLint *)& sInfo.aCompSize[GLRenderBufferInfo::STENCIL] ), ret );
		
		//if ( C_GL_NV_framebuffer_multisample_coverage ) {
		//	GL_CALL_BA( glGetNamedRenderbufferParameteriv( _uID, GL_RENDERBUFFER_COVERAGE_SAMPLES_NV,	& temp ), ret );
		//	GL_CALL_BA( glGetNamedRenderbufferParameteriv( _uID, GL_RENDERBUFFER_COLOR_SAMPLES_NV,		& temp ), ret );
		//}

		return ret;
	}


/*
=================================================
	
=================================================
*/
	void GLRenderBuffer::Attach(GLFrameBuffer *pFBO, gl_fbo_attach::type eAttach, uint uLevel, uint uLayer)
	{
		pFBO->Attach( *this, eAttach );
	}

/*
=================================================
	
=================================================
*/
	bool GLRenderBuffer::s_CheckRenderBufferFunctions()
	{
		return ( glBindRenderbuffer and glTextureRenderbuffer and glGetRenderbufferParameteriv and
				 glGetNamedRenderbufferParameteriv and glNamedRenderbufferStorageMultisampleCoverageNV and
				 glNamedRenderbufferStorageMultisample and glNamedRenderbufferStorage );
	}

//-------------------------------------------------------------------
	
}	// GLShell
}	// UX_STL